<template>
    <div class="product-list-page">
        <el-card shadow="hover" class="product-list-card">
            <div class="product-list-toolbar">
                <el-input v-model="keyword" placeholder="搜索商品名" style="width: 200px" @keyup.enter="handleSearch" />
                <el-select v-model="filterCategoryId" placeholder="商品分类" clearable style="width: 150px"
                    @change="handleSearch">
                    <el-option v-for="item in productCategoryList || []" :key="item.id" :label="item.name"
                        :value="item.id" />
                </el-select>
                <el-select v-model="filterUserCategoryId" placeholder="用户分类" clearable style="width: 150px"
                    @change="handleSearch">
                    <el-option v-for="item in userCategoryList || []" :key="item.id" :label="item.name"
                        :value="item.id" />
                </el-select>
                <el-button type="primary" @click="handleSearch">搜索</el-button>
                <el-button type="primary" @click="handleAdd">新增商品</el-button>
            </div>
            <el-table :data="list" style="width: 100%" stripe border>
                <el-table-column prop="id" label="ID" width="80" />
                <el-table-column prop="name" label="商品名" />
                <el-table-column prop="price" label="价格" />
                <el-table-column prop="stock" label="库存" />
                <el-table-column prop="logo" label="Logo图" width="100">
                    <template #default="scope">
                        <el-image v-if="scope.row.logo"
                            :src="BASE_URL + (typeof scope.row.logo === 'string' ? scope.row.logo : '')"
                            style="width: 40px; height: 40px; border-radius: 8px; border: 1px solid #eee;"
                            fit="cover" />
                    </template>
                </el-table-column>
                <el-table-column prop="images" label="详情图" width="120">
                    <template #default="scope">
                        <el-image
                            v-for="(img, idx) in (Array.isArray(scope.row.images) ? scope.row.images : (typeof scope.row.images === 'string' && scope.row.images.startsWith('[') ? JSON.parse(scope.row.images.replace(/\\/g, '')) : []))"
                            :key="idx" :src="(typeof img === 'string' ? img : '')"
                            style="width: 30px; height: 30px; margin-right: 4px; border-radius: 6px; border: 1px solid #eee;"
                            fit="cover" />
                    </template>
                </el-table-column>
                <el-table-column prop="product_category" label="商品分类">
                    <template #default="scope">
                        {{productCategoryList.find(c => c.id === scope.row.category_id)?.name ||
                            scope.row.product_category?.name || scope.row.category_id}}
                    </template>
                </el-table-column>
                <el-table-column prop="user_category" label="用户分类">
                    <template #default="scope">
                        {{userCategoryList.find(c => c.id === scope.row.user_category_id)?.name ||
                            scope.row.user_category?.name || scope.row.user_category_id}}
                    </template>
                </el-table-column>
                <el-table-column prop="created_at" label="创建时间">
                    <template #default="scope">
                        {{ formatDate(scope.row.created_at) }}
                    </template>
                </el-table-column>
                <el-table-column label="操作" width="180">
                    <template #default="scope">
                        <el-button size="small" @click="handleEdit(scope.row)" class="action-btn">编辑</el-button>
                        <el-button size="small" type="danger" @click="handleDelete(scope.row.id)"
                            class="action-btn">删除</el-button>
                    </template>
                </el-table-column>
            </el-table>
            <el-pagination v-model:current-page="page" v-model:page-size="pageSize" :total="total"
                layout="total, prev, pager, next, sizes" :page-sizes="[10, 20, 50, 100]"
                @current-change="handlePageChange" @size-change="handleSizeChange"
                style="margin-top: 16px; text-align: right;" />
        </el-card>
        <el-dialog v-model="dialogVisible" :title="editId ? '编辑商品' : '新增商品'" width="500px" class="product-dialog">
            <el-form :model="editForm" :rules="rules" ref="formRef" label-width="90px">
                <el-form-item label="商品名" prop="name">
                    <el-input v-model="editForm.name" />
                </el-form-item>
                <el-form-item label="价格" prop="price">
                    <el-input v-model="editForm.price" type="number" />
                </el-form-item>
                <el-form-item label="库存" prop="stock">
                    <el-input v-model="editForm.stock" type="number" />
                </el-form-item>
                <el-form-item label="Logo图" prop="logo">
                    <el-upload class="avatar-uploader" :action="uploadUrl" :show-file-list="false"
                        :on-success="handleLogoSuccess" :before-upload="beforeLogoUpload" :headers="uploadHeaders">
                        <img v-if="editForm.logo" :src="BASE_URL + editForm.logo" class="avatar avatar-preview" />
                        <el-icon v-else class="avatar-uploader-icon">
                            <Plus />
                        </el-icon>
                    </el-upload>
                </el-form-item>
                <el-form-item label="详情图" prop="images">
                    <el-upload :action="uploadUrl" list-type="picture-card" :file-list="detailFileList"
                        :on-success="handleDetailSuccess" :on-remove="handleDetailRemove" :headers="uploadHeaders"
                        multiple class="detail-uploader">
                        <el-icon class="detail-uploader-icon">
                            <Plus />
                        </el-icon>
                    </el-upload>
                </el-form-item>
                <el-form-item label="商品分类" prop="category_id">
                    <el-select v-model="editForm.category_id" placeholder="请选择商品分类">
                        <el-option v-for="item in productCategoryList" :key="item.id" :label="item.name"
                            :value="item.id" />
                    </el-select>
                </el-form-item>
                <el-form-item label="用户分类" prop="user_category_id">
                    <el-select v-model="editForm.user_category_id" placeholder="请选择用户分类">
                        <el-option v-for="item in userCategoryList" :key="item.id" :label="item.name"
                            :value="item.id" />
                    </el-select>
                </el-form-item>
                <el-form-item label="描述" prop="description">
                    <el-input v-model="editForm.description" type="textarea" />
                </el-form-item>
            </el-form>
            <template #footer>
                <div class="dialog-footer">
                    <el-button @click="dialogVisible = false">取消</el-button>
                    <el-button type="primary" @click="handleSave">保存</el-button>
                </div>
            </template>
        </el-dialog>
    </div>
</template>

<script lang="ts" setup>
import { Plus } from '@element-plus/icons-vue'
import { ref, reactive, computed } from 'vue'
import { ElMessage, ElMessageBox } from 'element-plus'
import { getProductList, createProduct, updateProduct, deleteProduct } from '../api/product'
import { getCategoryList as getUserCategoryList, type CategoryItem } from '../api/category'
import { getCategoryList as getProductCategoryList, type ProductCategoryItem } from '../api/productCategory'

const list = ref<any[]>([])
const total = ref(0)
const page = ref(1)
const pageSize = ref(10)
const keyword = ref('')
const BASE_URL = (import.meta as any).env.VITE_API_BASE_URL.replace(/\/api$/, '')
const dialogVisible = ref(false)
const editForm = ref<any>({})
const editId = ref<number | null>(null)

const uploadUrl = computed(() => {
    return BASE_URL + '/api/upload'
})

const productCategoryList = ref<ProductCategoryItem[]>([])
const userCategoryList = ref<CategoryItem[]>([])

const filterCategoryId = ref<number | null>(null)
const filterUserCategoryId = ref<number | null>(null)

const formRef = ref()
const rules = reactive({
    name: [{ required: true, message: '请输入商品名', trigger: 'blur' }],
    price: [{ required: true, message: '请输入价格', trigger: 'blur' }],
    stock: [{ required: true, message: '请输入库存', trigger: 'blur' }],
    category_id: [{ required: true, message: '请选择商品分类', trigger: 'change' }],
    user_category_id: [{ required: true, message: '请选择用户分类', trigger: 'change' }]
})

const uploadHeaders = computed(() => ({
    Authorization: localStorage.getItem('token') ? `Bearer ${localStorage.getItem('token')}` : ''
}))
const detailFileList = ref<any[]>([])
function handleLogoSuccess(res: any) {
    editForm.value.logo = (res.url)
}
function beforeLogoUpload(file: File) {
    const isImage = file.type.startsWith('image/')
    if (!isImage) {
        ElMessage.error('只能上传图片文件')
    }
    return isImage
}
function handleDetailSuccess(res: any, file: any) {
    if (!editForm.value.images) editForm.value.images = []
    const fullUrl = BASE_URL + (res.url)
    editForm.value.images.push(fullUrl)
    detailFileList.value.push({ url: fullUrl, name: file.name })
}
function handleDetailRemove(file: any) {
    if (editForm.value.images) {
        editForm.value.images = editForm.value.images.filter((url: string) => url !== file.url)
    }
    detailFileList.value = detailFileList.value.filter(f => f.url !== file.url)
}

const fetchProductCategory = async () => {
    const res = await getProductCategoryList()
    productCategoryList.value = Array.isArray(res.list) ? res.list : []
}
const fetchUserCategory = async () => {
    const res = await getUserCategoryList()
    userCategoryList.value = Array.isArray(res.list) ? res.list : []
}
const fetchList = async () => {
    const params: any = { page: page.value, pageSize: pageSize.value, keyword: keyword.value }
    if (filterCategoryId.value) params.category_id = filterCategoryId.value
    if (filterUserCategoryId.value) params.user_category_id = filterUserCategoryId.value
    const res = await getProductList(params)
    list.value = res.list
    total.value = res.total
}
const handleSearch = () => {
    page.value = 1
    fetchList()
}
const handlePageChange = (val: number) => {
    page.value = val
    fetchList()
}
const handleSizeChange = (val: number) => {
    pageSize.value = val
    page.value = 1
    fetchList()
}

function getFullUrl(url: string) {
    if (!url) return ''
    return BASE_URL + url
}
// 打开弹窗时同步fileList
const handleAdd = () => {
    editId.value = null
    editForm.value = { stock: 0, price: 0, category_id: productCategoryList.value[0]?.id, user_category_id: userCategoryList.value[0]?.id, images: [] }
    detailFileList.value = []
    dialogVisible.value = true
}
const handleEdit = (row: any) => {
    editId.value = row.id
    let imgs: string[] = []
    if (Array.isArray(row.images)) {
        imgs = row.images
    } else if (typeof row.images === 'string' && row.images.startsWith('[')) {
        try { imgs = JSON.parse(row.images.replace(/\\/g, '')) } catch { imgs = [] }
    }
    // logo字段也去除反斜杠
    let logo = row.logo
    if (typeof logo === 'string') logo = logo.replace(/\\/g, '')
    editForm.value = { ...row, images: imgs, logo: (logo) }
    detailFileList.value = (editForm.value.images || []).map((url: string, idx: number) => ({ url, name: `图片${idx + 1}` }))
    dialogVisible.value = true
}
const handleSave = async () => {
    await formRef.value.validate(async (valid: boolean) => {
        if (!valid) return
        if (editId.value) {
            await updateProduct(editId.value, editForm.value)
            ElMessage.success('修改成功')
        } else {
            await createProduct(editForm.value)
            ElMessage.success('新增成功')
        }
        dialogVisible.value = false
        page.value = 1
        fetchList()
    })
}
const handleDelete = (id: number) => {
    ElMessageBox.confirm('确定要删除该商品吗？', '提示', { type: 'warning' })
        .then(async () => {
            await deleteProduct(id)
            ElMessage.success('删除成功')
            fetchList()
        })
}
function formatDate(val: string) {
    if (!val) return ''
    const d = new Date(val)
    return d.toLocaleString()
}
fetchProductCategory()
fetchUserCategory()
fetchList()
</script>

<style scoped>
.product-list-page {
    padding: 24px;
    background: #fff;
    min-height: 0;
    height: 100%;
    box-sizing: border-box;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: flex-start;
}

.product-list-card {
    width: 100%;
    max-width: 100%;
    margin: 0;
    border-radius: 10px;
    box-sizing: border-box;
}

.product-list-toolbar {
    margin-bottom: 16px;
    display: flex;
    align-items: center;
    gap: 12px;
}

.action-btn {
    margin-right: 8px;
}

.product-dialog .el-dialog__body {
    padding: 32px 32px 12px 32px;
    border-radius: 16px;
    background: #f8fafc;
}

.avatar-uploader {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 90px;
    height: 90px;
    border: 1px dashed #d9d9d9;
    border-radius: 8px;
    background: #fafbfc;
    cursor: pointer;
    transition: border-color 0.3s;
}

.avatar-uploader:hover {
    border-color: #409eff;
}

.avatar-uploader-icon {
    font-size: 32px;
    color: #bfbfbf;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 100%;
    height: 100%;
}

.avatar-preview {
    width: 88px;
    height: 88px;
    border-radius: 8px;
    object-fit: cover;
    border: none;
    margin: 1px;
}

.detail-uploader {
    min-width: 120px;
}

.detail-uploader-icon {
    font-size: 28px;
    color: #bfbfbf;
}

.el-upload-list--picture-card .el-upload-list__item {
    border-radius: 8px;
    margin-right: 8px;
}

.el-form-item {
    margin-bottom: 18px;
}

.el-dialog__body {
    padding-top: 18px;
}
</style>
